package business

import (
	"bytes"
	"fmt"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/business"
	businessReq "github.com/flipped-aurora/gin-vue-admin/server/model/business/request"
	businessRes "github.com/flipped-aurora/gin-vue-admin/server/model/business/response"
	"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
	"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
	"github.com/flipped-aurora/gin-vue-admin/server/service"
	"github.com/flipped-aurora/gin-vue-admin/server/utils"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"github.com/xuri/excelize/v2"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"net/http"
	"strconv"
	"sync"
	"time"
)

type InvitationApi struct {
}

var invitationService = service.ServiceGroupApp.BusinessServiceGroup.InvitationService

// CreateInvitation 创建邀请
// @Tags Invitation
// @Summary 创建邀请
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body business.Invitation true "创建邀请"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /invitation/createInvitation [post]
func (invitationApi *InvitationApi) CreateInvitation(c *gin.Context) {
	var invitation business.Invitation
	err := c.ShouldBindJSON(&invitation)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	isAdmin := utils.GetUserIsAdmin(c)
	userId := utils.GetUserID(c)
	//当不是管理员时
	if isAdmin == 2 {
		invitation.UserId = userId
	}
	if err := invitationService.CreateInvitation(&invitation); err != nil {
		global.GVA_LOG.Error("创建失败!", zap.Error(err))
		response.FailWithMessage("创建失败", c)
	} else {
		response.OkWithMessage("创建成功", c)
	}
}

// DeleteInvitation 删除邀请
// @Tags Invitation
// @Summary 删除邀请
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body business.Invitation true "删除邀请"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /invitation/deleteInvitation [delete]
func (invitationApi *InvitationApi) DeleteInvitation(c *gin.Context) {
	var invitation business.Invitation
	err := c.ShouldBindJSON(&invitation)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	isAdmin := utils.GetUserIsAdmin(c)
	userId := utils.GetUserID(c)
	//当不是管理员时
	if isAdmin == 2 {
		invitation.UserId = userId
	}
	if err := invitationService.DeleteInvitation(invitation); err != nil {
		global.GVA_LOG.Error("删除失败!", zap.Error(err))
		response.FailWithMessage("删除失败", c)
	} else {
		response.OkWithMessage("删除成功", c)
	}
}

// DeleteInvitationByIds 批量删除邀请
// @Summary 批量删除邀请
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "批量删除邀请"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"批量删除成功"}"
// @Router /invitation/deleteInvitationByIds [delete]
func (invitationApi *InvitationApi) DeleteInvitationByIds(c *gin.Context) {
	var IDS request.IdsReq
	err := c.ShouldBindJSON(&IDS)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	isAdmin := utils.GetUserIsAdmin(c)
	userId := utils.GetUserID(c)
	var userIdInfo uint
	//当不是管理员时
	if isAdmin == 2 {
		userIdInfo = userId
	}
	if err := invitationService.DeleteInvitationByIds(IDS, userIdInfo); err != nil {
		global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
		response.FailWithMessage("批量删除失败", c)
	} else {
		response.OkWithMessage("批量删除成功", c)
	}
}

// UpdateInvitation 更新邀请
// @Tags Invitation
// @Summary 更新邀请
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body business.Invitation true "更新邀请"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /invitation/updateInvitation [put]
func (invitationApi *InvitationApi) UpdateInvitation(c *gin.Context) {
	var invitation business.Invitation
	err := c.ShouldBindJSON(&invitation)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := invitationService.UpdateInvitation(invitation); err != nil {
		global.GVA_LOG.Error("更新失败!", zap.Error(err))
		response.FailWithMessage("更新失败", c)
	} else {
		response.OkWithMessage("更新成功", c)
	}
}

// FindInvitation 用id查询邀请
// @Tags Invitation
// @Summary 用id查询邀请
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query business.Invitation true "用id查询邀请"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /invitation/findInvitation [get]
func (invitationApi *InvitationApi) FindInvitation(c *gin.Context) {
	var invitation business.Invitation
	err := c.ShouldBindQuery(&invitation)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	isAdmin := utils.GetUserIsAdmin(c)
	userId := utils.GetUserID(c)

	//管理员判断
	if isAdmin == 2 {
		invitation.UserId = userId
	}
	if reinvitation, err := invitationService.GetInvitation(invitation.ID, invitation.UserId); err != nil {
		global.GVA_LOG.Error("查询失败!", zap.Error(err))
		response.FailWithMessage("查询失败", c)
	} else {
		response.OkWithData(gin.H{"reinvitation": reinvitation}, c)
	}
}

// GetInvitationList 分页获取邀请列表
// @Tags Invitation
// @Summary 分页获取邀请列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query businessReq.InvitationSearch true "分页获取邀请列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /invitation/getInvitationList [get]
func (invitationApi *InvitationApi) GetInvitationList(c *gin.Context) {
	var pageInfo businessReq.InvitationSearch
	err := c.ShouldBindQuery(&pageInfo)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	userId := utils.GetUserID(c)
	pageInfo.UserId = userId
	if list, total, err := invitationService.GetInvitationInfoList(pageInfo); err != nil {
		global.GVA_LOG.Error("获取失败!", zap.Error(err))
		response.FailWithMessage("获取失败", c)
	} else {
		response.OkWithDetailed(response.PageResult{
			List:     list,
			Total:    total,
			Page:     pageInfo.Page,
			PageSize: pageInfo.PageSize,
		}, "获取成功", c)
	}
}

// AdminGetInvitationList 管理员分页获取邀请列表
// @Tags Invitation
// @Summary 分页获取邀请列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query businessReq.InvitationSearch true "分页获取邀请列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /invitation/getInvitationList [get]
func (invitationApi *InvitationApi) AdminGetInvitationList(c *gin.Context) {
	var pageInfo businessReq.InvitationSearch
	err := c.ShouldBindQuery(&pageInfo)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	isAdmin := utils.GetUserIsAdmin(c)
	if isAdmin == 1 {
		list, total, err := invitationService.GetInvitationInfoList(pageInfo)
		if err != nil {
			global.GVA_LOG.Error("获取失败!", zap.Error(err))
			response.FailWithMessage("获取失败", c)
			return
		}
		//赋值
		var invitationAdminQueryList []businessRes.InvitationAdminQuery
		err = copier.Copy(&invitationAdminQueryList, &list)
		if err != nil {
			global.GVA_LOG.Error("赋值时发生错误!", zap.Error(err))
			response.FailWithMessage("赋值时发生错误", c)
			return
		}

		//附带用户信息
		//定义用户数组
		var userIdList []uint
		for _, v := range invitationAdminQueryList {
			userIdList = append(userIdList, v.UserId)
		}
		userList, err := userService.FindUserByIdList(userIdList)
		if err != nil {
			global.GVA_LOG.Error("获取用户信息失败!", zap.Error(err))
			response.FailWithMessage("获取用户信息失败", c)
		}
		//定义用户map
		userMap := make(map[uint]businessRes.UserInfo)
		for _, v := range userList {
			userMap[v.ID] = businessRes.UserInfo{
				ID:       v.ID,
				NickName: v.NickName,
				Username: v.Username,
			}
		}

		for k, v := range invitationAdminQueryList {
			invitationAdminQueryList[k].UserInfo = userMap[v.UserId]
		}
		response.OkWithDetailed(response.PageResult{
			List:     list,
			Total:    total,
			Page:     pageInfo.Page,
			PageSize: pageInfo.PageSize,
		}, "获取成功", c)
	} else {
		response.FailWithMessage("你没有权限", c)
	}
}

// 上传答题人员
func (invitationApi *InvitationApi) InvitationUpExcel(c *gin.Context) {
	file, _, err := c.Request.FormFile("file")
	if err != nil {
		panic(err)
	}
	questionnaireUuid := c.Request.Form.Get("questionnaireUuid")
	userIdStr := c.Request.Form.Get("user_id")
	if userIdStr == "" {
		userIdStr = "0"
	}
	userIdInfo, err := strconv.Atoi(userIdStr)
	if err != nil {
		response.FailWithMessage("发生错误", c)
		return
	}
	userId := uint(userIdInfo)
	if utils.GetUserIsAdmin(c) == 2 {
		userId = utils.GetUserID(c)
	}

	var invitation business.Invitation
	var invitationList []*business.Invitation
	f, err := excelize.OpenReader(file)
	if err != nil {
		panic(err)
	}
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	rows, err := f.GetRows("答题人员信息")
	if err != nil {
		response.FailWithMessage("你没有使用模板", c)
		return
	}
	for i := 1; i < len(rows); i++ {
		//保证长度为1
		for j := len(rows[i]); j < 1; j++ {
			rows[i] = append(rows[i], "")
		}
		invitation.ID = gorm.Model{}.ID
		invitation.UserId = userId
		invitation.Name = rows[i][0]
		invitation.Phone = rows[i][1]
		invitation.QuestionnaireUuid = questionnaireUuid
		invitationList = append(invitationList, &invitation)
	}
	err = invitationService.CreateInvitationByExcel(questionnaireUuid, userId, invitationList)
	if err != nil {
		response.FailWithMessage("err", c)
		return
	}
	response.OkWithMessage("添加成功", c)
}

//发送短息给邀请人

func SendEmails(c *gin.Context) {

	var msg businessReq.SendEmail
	err := c.BindJSON(&msg)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
	}
	inviationList, _, err := invitationService.GetInvitationInfoList(businessReq.InvitationSearch{Invitation: business.Invitation{QuestionnaireUuid: msg.QuestionnaireUuid}})
	if err != nil {
		response.FailWithMessage(err.Error(), c)
	}
	var wg sync.WaitGroup
	wg.Add(len(inviationList))
	for i := 0; i < len(inviationList); i++ {
		c := inviationList[i]
		go func() {
			appKey := "106829"
			timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10)
			mobile := c.Phone
			content := msg.Msg
			spNumber := ""
			sendTime := ""
			reportUrl := ""
			moUrl := ""
			attach := ""
			appSecret := "b874dcb9422ddc8e"
			sign := utils.GetMD5Encode(appKey + timestamp + mobile + content + spNumber + spNumber + sendTime + appSecret)
			url := "http://182.92.7.106:7892/api/sms/air/send"
			requestBody := fmt.Sprintf(`{"appKey":"%s",
	"timestamp": "%s",
	"content":"%s",
	"mobile":"%s",
	"spNumber":"%s",
	"sendTime":"%s",
	"reportUrl":"%s",
	"moUrl":"%s",
	"attach":"%s",
	"sign":"%s"
	}`, appKey, timestamp, content, c.Phone, spNumber, sendTime, reportUrl, moUrl, attach, sign)
			var jsonStr = []byte(requestBody)
			req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
			req.Header.Set("Content-Type", "application/json")
			resp, err := http.DefaultClient.Do(req)
			if resp != nil {
				defer resp.Body.Close()
			}
			if err != nil {
				panic(err)
			}
			//body, _ := ioutil.ReadAll(resp.Body)
			////var data interface{}
			//type Data struct {
			//	Message string `json:"message"`
			//	Status int `json:"status"`
			//	TaskId interface{} `json:"taskId"`
			//}
			//var data Data
			////fmt.Println("response Body:", string(body))
			//fmt.Println(response.Body)
			//fmt.Println(response)
			//fmt.Println(data)
			//err = json.Unmarshal([]byte(string(body)), &data)
			//fmt.Println(data)
			wg.Done()
		}()
	}
	wg.Wait()
	c.JSON(200, gin.H{"do": 1, "msg": "发送完毕"})
}
